/*
 * Test performance counter of RapidIO port.
 *
 * The program querys the performance counter of SRIO port and print the result.
 * The RapidIO port has eight performance monitoring counters that 
 * can be independently configured.
 */

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <rio_mport_lib.h>

#ifdef __cplusplus
extern "C" {
#endif


#define RIO_SPx_PCNTR_CTL(x)	(0x14110 + 0x4*(x))
#define RIO_SPx_PCNTR_EN        0x14100
#define RIO_SPx_PCNTR_CNT(x)    (0x14130 + 0x4*(x))


static void usage(char *program)
{
	printf("%s - \n", program);
	printf("	Show performance counter of SRIO port.Firstly you must run this program\n"); 
	printf("	to enable the counters, then run it again to show the value of counters.\n");
	printf("Usage:\n");
	printf("	%s [options]\n", program);
	printf("Options are:\n");
	printf("    <mport> local mport device index\n");
	printf("    <flag> 0-show Pkt counters  1-show Drop counters\n");
	printf("\n");
}


int main(int argc, char **argv)
{	
	int fd;
	uint32_t mport_id = 0;
	int rc = EXIT_SUCCESS;
	uint32_t data;	
	uint32_t op_size = 4;
	uint32_t flag;
	
	/* Parse console arguments */
	if (argc < 3) {
		usage(argv[0]);		
		exit(EXIT_FAILURE);
	}

	mport_id = strtoul(argv[1], NULL, 0);

	flag  = strtoul(argv[2], NULL, 0);
	
	fd = rio_mport_open(mport_id, 0);
	if (fd < 0) {
		printf("Unable to open mport%d device err=%d\n",
			mport_id, errno);
		exit(EXIT_FAILURE);
	}
	if(flag){
		rio_lcfg_write(fd, RIO_SPx_PCNTR_CTL(0), op_size, 0xFF8A);
		rio_lcfg_write(fd, RIO_SPx_PCNTR_CTL(1), op_size, 0xFF0A);
	}else{
		rio_lcfg_write(fd, RIO_SPx_PCNTR_CTL(0), op_size, 0xFF80);
		rio_lcfg_write(fd, RIO_SPx_PCNTR_CTL(1), op_size, 0xFF00);
	}
	rio_lcfg_write(fd, RIO_SPx_PCNTR_CTL(2), op_size, 0xFF88);
	rio_lcfg_write(fd, RIO_SPx_PCNTR_CTL(3), op_size, 0xFF08);
	rio_lcfg_write(fd, RIO_SPx_PCNTR_CTL(4), op_size, 0xFF89);
	rio_lcfg_write(fd, RIO_SPx_PCNTR_CTL(5), op_size, 0xFF09);
	rio_lcfg_write(fd, RIO_SPx_PCNTR_CTL(6), op_size, 0xFF81);
	rio_lcfg_write(fd, RIO_SPx_PCNTR_CTL(7), op_size, 0xFF01);
	rio_lcfg_write(fd, RIO_SPx_PCNTR_EN, op_size, 0x80000000);

	rc = rio_lcfg_read(fd, RIO_SPx_PCNTR_CNT(0), op_size, &data);
	if (rc){
		printf("Read Error %d\n", rc);
		rc = EXIT_FAILURE;			
	}else{
		if(flag==0)		
			printf("Tx_Pkt_cnt:  0x%08x\n",data);
		else
			printf("Tx_Drop_cnt: 0x%08x\n",data);
	}

	rc = rio_lcfg_read(fd, RIO_SPx_PCNTR_CNT(1), op_size, &data);
	if (rc){
		printf("Read Error %d\n", rc);
		rc = EXIT_FAILURE;			
	}else{
		if(flag==0)
			printf("Rx_Pkt_cnt:  0x%08x\n",data);
		else		
			printf("Rx_Drop_cnt: 0x%08x\n",data);	
	}

	rc = rio_lcfg_read(fd, RIO_SPx_PCNTR_CNT(2), op_size, &data);
	if (rc){
		printf("Read Error %d\n", rc);
		rc = EXIT_FAILURE;			
	}else
		printf("Tx_Retry_cnt:0x%08x\n",data);

	rc = rio_lcfg_read(fd, RIO_SPx_PCNTR_CNT(3), op_size, &data);
	if (rc){
		printf("Read Error %d\n", rc);
		rc = EXIT_FAILURE;			
	}else
		printf("Rx_Retry_cnt:0x%08x\n",data);

	rc = rio_lcfg_read(fd, RIO_SPx_PCNTR_CNT(4), op_size, &data);
	if (rc){
		printf("Read Error %d\n", rc);
		rc = EXIT_FAILURE;			
	}else
		printf("Tx_PNA_cnt:  0x%08x\n",data);

	rc = rio_lcfg_read(fd, RIO_SPx_PCNTR_CNT(5), op_size, &data);
	if (rc){
		printf("Read Error %d\n", rc);
		rc = EXIT_FAILURE;			
	}else
		printf("Rx_PNA_cnt:  0x%08x\n",data);

	rc = rio_lcfg_read(fd, RIO_SPx_PCNTR_CNT(6), op_size, &data);
	if (rc){
		printf("Read Error %d\n", rc);
		rc = EXIT_FAILURE;			
	}else
		printf("Tx_SWpkt_cnt:0x%08x\n",data);

	rc = rio_lcfg_read(fd, RIO_SPx_PCNTR_CNT(7), op_size, &data);
	if (rc){
		printf("Read Error %d\n", rc);
		rc = EXIT_FAILURE;			
	}else
		printf("Rx_SWpkt_cnt:0x%08x\n",data);

	/* Close the mport fd */
	close(fd);
	exit(rc);
}

#ifdef __cplusplus
}
#endif

